package com.sybil.spa.dao;

import com.sybil.spa.dominio.DetalleSolicitud;
import com.sybil.spa.dominio.Solicitud;
import com.sybil.spa.dominio.SolicitudPK;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

@Repository("solicitudDAO")
public class SolicitudDAO extends AbstractDAO<Solicitud, SolicitudPK> {

   private final String[] tipos = {"RE", "GE"};

   public SolicitudDAO() {
      super(Solicitud.class);
   }

   public Solicitud getSolicitud(SolicitudPK llave) {
      return obtener(llave);
   }

   public Solicitud getSolicitud(String claveFlujo, int numeroSolicitud) {
      return obtener(new SolicitudPK(claveFlujo, numeroSolicitud));
   }

   public List<Solicitud> getSolicitudes() {
      return obtener();
   }

   public List<Solicitud> getSolicitudes(String claveUsuario) {
      Criteria c = getCriteria();
      c.add(Restrictions.eq("terminado", "N"));
      c.createAlias("flujo", "f");
      c.add(Restrictions.in("f.tipo", tipos));
      c.createAlias("paso", "p");
      c.add(Restrictions.eq("p.jerarquico", "N"));
      c.createAlias("p.responsables", "r");
      c.add(Restrictions.eq("r.esAprobador", "S"));
      c.add(Restrictions.eq("r.llave.claveUsuario", claveUsuario));
      c.addOrder(Order.asc("llave.claveFlujo"));
      c.addOrder(Order.desc("llave.numeroSolicitud"));

      Criteria c2 = getCriteria();
      c2.add(Restrictions.eq("terminado", "N"));
      c2.add(Restrictions.eq("asignadoA", claveUsuario));
      c2.createAlias("flujo", "f");
      c2.add(Restrictions.in("f.tipo", tipos));
      c2.addOrder(Order.asc("llave.claveFlujo"));
      c2.addOrder(Order.desc("llave.numeroSolicitud"));

      List<Solicitud> list = c.list();
      list.addAll(c2.list());

      if (!list.isEmpty()) {
         Iterator<Solicitud> i = list.iterator();
         while (i.hasNext()) {
            Solicitud solicitud = i.next();
            List<DetalleSolicitud> detalles = solicitud.getDetalles();
            for (DetalleSolicitud detalle : detalles) {
               if (detalle.getInstancia() == solicitud.getInstancia()) {
                  if (solicitud.getPaso().equals(detalle.getEvento().getPaso())) {
                     if (detalle.getClaveUsuario().equals(claveUsuario)) {
                        i.remove();
                     }
                  }
               }
            }
         }
      }
      return list;
   }

   public void guardarSolicitud(Solicitud solicitud) {
      guardar(solicitud);
   }

   public void editarSolicitud(Solicitud solicitud) {
      editar(solicitud);
   }

   public void eliminarSolicitud(Solicitud solicitud) {
      eliminar(solicitud);
   }

   public Integer getSecuencia(String claveFlujo) {
      Integer siguiente = 0;
      Query query = sesionActual().getNamedQuery("Solicitud.maxPorFlujo")
              .setString("claveFlujo", claveFlujo);
      List list = query.list();
      Object get = list.get(0);
      if (get != null) {
         siguiente = (Integer) list.get(0);
      }
      siguiente++;
      return siguiente;
   }

   public Integer getNumeroInstancia(String claveFlujo, int numero) {
      Integer siguiente = 0;
      Query query = sesionActual().getNamedQuery("Solicitud.instanciaActual")
              .setString("claveFlujo", claveFlujo).setInteger("numero", numero);
      List list = query.list();
      Object get = list.get(0);
      if (get != null) {
         siguiente = (Integer) list.get(0);
      }
      siguiente++;
      return siguiente;
   }

   public List<Solicitud> getHistorico(String claveFlujo, Date fechaDesde,
           Date fechaHasta, String estatus, int numeroSolicitud) {
      Criteria c = getCriteria();
      c.createAlias("flujo", "f");
      c.add(Restrictions.in("f.tipo", tipos));
      if (claveFlujo != null && !"".equals(claveFlujo)) {
         c.add(Restrictions.eq("llave.claveFlujo", claveFlujo));
      }
      if (numeroSolicitud != 0) {
         c.add(Restrictions.eq("llave.numeroSolicitud", numeroSolicitud));
      }
      if (estatus != null && !"T".equals(estatus)) {
         if ("A".equals(estatus)) {
            c.add(Restrictions.eq("terminado", "S"))
                    .add(Restrictions.eq("finalCorrecto", "S"));
         } else if ("P".equals(estatus)) {
            c.add(Restrictions.eq("terminado", "S"))
                    .add(Restrictions.eq("finalCorrecto", "N"));
         } else {
            c.add(Restrictions.eq("terminado", "N"));
         }
      }
      if (fechaDesde != null && fechaHasta != null) {
         c.add(Restrictions.between("fecha", fechaDesde, fechaHasta));
      }
      c.addOrder(Order.asc("llave.claveFlujo"));
      c.addOrder(Order.desc("llave.numeroSolicitud"));
      return c.list();
   }
}
